package com.my.lucky.service;

import com.my.lucky.config.IwencaiConfig;
import com.my.lucky.entity.StockLimitUp;
import com.my.lucky.repository.StockLimitUpRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 涨停数据查询服务
 */
@Slf4j
@Service
public class StockLimitUpService {

    @Autowired
    private StockLimitUpRepository stockLimitUpRepository;

    @Autowired
    private IWencaiServiceTools iwencaiServiceTools;
    @Autowired
    private IwencaiConfig iwencaiConfig;

    /**
     * 根据多条件查询涨停数据（支持分页）
     *
     * @param startDate       开始日期
     * @param endDate         结束日期
     * @param stockCodeOrName 股票代码或名称（模糊查询）
     * @param consecutiveDays 几天几板
     * @param limitUpType     涨停类型
     * @param page            页码（从0开始）
     * @param size            每页大小
     * @param sortField       排序字段
     * @param sortDirection   排序方向（asc/desc）
     * @return 分页结果
     */
    public Page<StockLimitUp> searchLimitUpStocks(LocalDate startDate, LocalDate endDate,
                                                  String stockCodeOrName, String consecutiveDays, String gainian,
                                                  String limitUpType, int page, int size,
                                                  String sortField, String sortDirection) {

        // 创建动态查询条件
        Specification<StockLimitUp> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 日期范围查询
            if (startDate != null) {
                LocalDateTime startDateTime = startDate.atStartOfDay();
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("recordTime"), startDateTime));
            }
            if (endDate != null) {
                LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("recordTime"), endDateTime));
            }

//            // 股票代码或名称模糊查询
//            if (stockCodeOrName != null && !stockCodeOrName.trim().isEmpty()) {
//                String searchTerm = "%" + stockCodeOrName.trim() + "%";
//                Predicate codePredicate = criteriaBuilder.like(root.get("stockCode"), searchTerm);
//                Predicate namePredicate = criteriaBuilder.like(root.get("stockName"), searchTerm);
//                predicates.add(criteriaBuilder.or(codePredicate, namePredicate));
//            }

            // 修改后的代码支持两种查询模式：
            // 1. 当输入包含逗号时，使用IN精确查询
            // 2. 当输入不包含逗号时，使用LIKE模糊查询
            if (gainian != null && !gainian.trim().isEmpty()) {
                String input = gainian.trim();
                if (input.contains(",")) {
                    // 多值精确查询模式（IN操作符）
                    List<String> codes = Arrays.asList(input.split(","));
                    // 构建股票代码IN查询
                    CriteriaBuilder.In<String> codeIn = criteriaBuilder.in(root.get("allGainian"));
                    codes.forEach(codeIn::value);
                    // 构建股票名称IN查询
                    CriteriaBuilder.In<String> nameIn = criteriaBuilder.in(root.get("allGainian"));
                    codes.forEach(nameIn::value);
                    // 组合条件（代码IN或名称IN）
                    predicates.add(criteriaBuilder.or(codeIn, nameIn));
                } else {
                    // 单值模糊查询模式（LIKE操作符）
                    String searchTerm = "%" + input + "%";
//                    Predicate codePredicate = criteriaBuilder.like(root.get("allGainian"), searchTerm);
//                    Predicate namePredicate = criteriaBuilder.like(root.get("allGainian"), searchTerm);
//                    predicates.add(criteriaBuilder.or(codePredicate, namePredicate));
                }
            }

            // 修改后的代码支持两种查询模式：
            // 1. 当输入包含逗号时，使用IN精确查询
            // 2. 当输入不包含逗号时，使用LIKE模糊查询
            if (stockCodeOrName != null && !stockCodeOrName.trim().isEmpty()) {
                String input = stockCodeOrName.trim();
                if (input.contains(",")) {
                    // 多值精确查询模式（IN操作符）
                    List<String> codes = Arrays.asList(input.split(","));
                    // 构建股票代码IN查询
                    CriteriaBuilder.In<String> codeIn = criteriaBuilder.in(root.get("stockCode"));
                    codes.forEach(codeIn::value);
                    // 构建股票名称IN查询
                    CriteriaBuilder.In<String> nameIn = criteriaBuilder.in(root.get("stockName"));
                    codes.forEach(nameIn::value);
                    // 组合条件（代码IN或名称IN）
                    predicates.add(criteriaBuilder.or(codeIn, nameIn));
                } else {
                    // 单值模糊查询模式（LIKE操作符）
                    String searchTerm = "%" + input + "%";
                    Predicate codePredicate = criteriaBuilder.like(root.get("stockCode"), searchTerm);
                    Predicate namePredicate = criteriaBuilder.like(root.get("stockName"), searchTerm);
                    predicates.add(criteriaBuilder.or(codePredicate, namePredicate));
                }
            }

            // 几天几板查询
            if (consecutiveDays != null && !consecutiveDays.trim().isEmpty()) {
                predicates.add(criteriaBuilder.like(root.get("consecutiveLimitUpCount"), "%" + consecutiveDays.trim() + "%"));
            }

            // 涨停类型查询
            if (limitUpType != null && !limitUpType.trim().isEmpty()) {
                predicates.add(criteriaBuilder.like(root.get("limitUpType"), "%" + limitUpType.trim() + "%"));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };

        // 创建排序
        Sort sort = Sort.by(Sort.Direction.ASC, "finalLimitUpTime"); // 默认按记录时间降序
        if (sortField != null && !sortField.trim().isEmpty()) {
            Sort.Direction direction = "asc".equalsIgnoreCase(sortDirection) ?
                    Sort.Direction.ASC : Sort.Direction.DESC;
            sort = Sort.by(direction, sortField);
        }

        // 创建分页对象
        Pageable pageable = PageRequest.of(page, size, sort);

        return stockLimitUpRepository.findAll(spec, pageable);
    }

    /**
     * 获取今日涨停股票
     */
    public List<StockLimitUp> getTodayLimitUpStocks() {
        try {
            LocalDate today = LocalDate.now();
//            LocalDate today = LocalDate.now().minusDays(1);
            log.info("获取今日({})涨停数据...", today);

            // 首先检查数据库中是否有今日的涨停数据
            List<StockLimitUp> todayLimitUpStocks = stockLimitUpRepository.findTodayLimitUpStocksAndRecordTimeBetween(LocalDateTime.of(today, LocalTime.MIN),LocalDateTime.of(today, LocalTime.MAX));

            if (!todayLimitUpStocks.isEmpty()) {
                log.info("从数据库获取到今日 {} 只涨停股票", todayLimitUpStocks.size());
                return todayLimitUpStocks;
            }

            // 如果数据库中没有今日数据，调用IWencaiServiceTools获取实时涨停数据
            log.info("数据库中没有今日涨停数据，调用接口查询...");
//            List<StockLimitUp> limitUpStocks = iwencaiServiceTools.searchLimitUp("今日涨停股票", iwencaiConfig.getIsLocal());
            List<StockLimitUp> limitUpStocks = iwencaiServiceTools.scheduleLimitUpTask();
            log.info("从接口获取到 {} 只涨停股票", limitUpStocks.size());
            return limitUpStocks;
        } catch (Exception e) {
            log.error("获取今日涨停数据失败", e);
            // 如果获取数据失败，返回空列表
            return new ArrayList<>();
        }
    }

    /**
     * 获取今日涨停股票
     */
    public List<StockLimitUp> getTodayLimitUpStocksBy(LocalDateTime startDate, LocalDateTime endDate) {
        try {
//            LocalDate today = LocalDate.now();
            log.info("获取今日({})涨停数据...", startDate);

            // 首先检查数据库中是否有今日的涨停数据
            List<StockLimitUp> todayLimitUpStocks = stockLimitUpRepository.findTodayLimitUpStocksAndRecordTimeBetween(startDate, endDate);

            if (!todayLimitUpStocks.isEmpty()) {
                log.info("从数据库获取到今日 {} 只涨停股票", todayLimitUpStocks.size());
                return todayLimitUpStocks;
            } else {
                return new ArrayList<>();
            }

            // 如果数据库中没有今日数据，调用IWencaiServiceTools获取实时涨停数据
//            log.info("数据库中没有今日涨停数据，调用接口查询...");
//            List<StockLimitUp> limitUpStocks = iwencaiServiceTools.searchLimitUp("今日涨停股票", iwencaiConfig.getIsLocal());
//            List<StockLimitUp> limitUpStocks = iwencaiServiceTools.scheduleLimitUpTask();
//            log.info("从接口获取到 {} 只涨停股票", limitUpStocks.size());
//            return limitUpStocks;
        } catch (Exception e) {
            log.error("获取今日涨停数据失败", e);
            // 如果获取数据失败，返回空列表
            return new ArrayList<>();
        }
    }

    /**
     * 根据股票代码查询历史涨停记录
     */
    public List<StockLimitUp> getStockLimitUpHistory(String stockCode) {
        return stockLimitUpRepository.findByStockCode(stockCode);
    }

    /**
     * 根据涨停原因关键词查询
     */
    public List<StockLimitUp> searchByReason(String keyword) {
        return stockLimitUpRepository.findByLimitUpReasonContaining(keyword);
    }

    /**
     * 统计指定日期的涨停股票数量
     */
    public Long countLimitUpStocksByDate(LocalDate date) {
        LocalDateTime dateTime = date.atStartOfDay();
        return stockLimitUpRepository.countByRecordDate(dateTime);
    }

    /**
     * 获取所有涨停类型（用于下拉选择）
     */
    public List<String> getAllLimitUpTypes() {
        // 这里可以根据实际需要从数据库查询或返回预定义的类型
        List<String> types = new ArrayList<>();
        types.add("一字涨停");
        types.add("放量涨停");
        types.add("缩量涨停");
        types.add("开板涨停");
        types.add("秒板涨停");
        return types;
    }

    /**
     * 获取所有几天几板选项（用于下拉选择）
     */
    public List<String> getAllConsecutiveDaysOptions() {
        List<String> options = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            options.add(i + "天" + i + "板");
        }
        options.add("首板涨停");
        options.add("2天1板");
        options.add("3天2板");
        options.add("4天3板");
        options.add("5天4板");
        return options;
    }
} 